package com.hitqz.robot.dispatch.netty;

import com.hitqz.robot.dispatch.netty.decoder.Server2RobotDecoder;
import com.hitqz.robot.dispatch.netty.encoder.Server2RobotEncoder;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.concurrent.CompletableFuture;

/**
 * @author xupkun
 * @date 2023/7/14
 */
@Slf4j
@Component
public class NettyServer implements CommandLineRunner {

	@Value("${custom.netty.port:#{null}}")
	private Integer customPort;

	@Override
	public void run(String... args) throws Exception {
		CompletableFuture.runAsync(()-> {
			try {
				Integer port = 9874;
				if (customPort != null) {
					port = customPort;
				}
				log.info("启动服务端端口:" + port);
				NettyServer.bind(port);
			} catch (Exception e) {
				log.info("bind() failed" + e.getMessage());
				throw new RuntimeException(e);
			}
		});
	}

	public static void bind(Integer port) {
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		try {
			log.info("正在启动服务端netty通讯端口成功{}", port );
			ServerBootstrap bootstrap = new ServerBootstrap();
			bootstrap.group(bossGroup, workerGroup)
					.childOption(ChannelOption.TCP_NODELAY, true)
					.channel(NioServerSocketChannel.class)
					.option(ChannelOption.SO_RCVBUF, 1024*1024)
					.option(ChannelOption.RCVBUF_ALLOCATOR,new FixedRecvByteBufAllocator(1024*1024))
					.childHandler(
							new ChannelInitializer<Channel>() {
								@Override
								protected void initChannel(Channel channel) throws Exception {
									channel.pipeline().addLast(new LengthFieldBasedFrameDecoder(
											1024*1024+46, // 最大帧长度（1 MB 数据 ）
											42,        // 长度字段的偏移量
											4,         // 长度字段的字节数
											0,         // 长度调整
											2         // 初始偏移量 跳过0xEB90
									));
									channel.pipeline().addLast(new Server2RobotDecoder());
									channel.pipeline().addLast(new Server2RobotEncoder());
									channel.pipeline().addLast(new NettyMessageHandler());
								}
							}
					);
			// 端口绑定
			ChannelFuture f = bootstrap.bind(port).sync();
			Channel channel = f.channel();
			f.channel().closeFuture().sync();
		} catch (Exception e) {
			log.error("启动 netty 失败:" + e.getMessage());
		} finally {
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}

}
